<!-- xl-drag-list 可拖拽列表组件 -->
<template>
  <view class="xl-drag-list-container">
    <view 
      class="drag-list"
      :style="{ height: listHeight }"
    >
      <view 
        v-for="(item, index) in displayList" 
        :key="item.id || index"
        :class="['drag-item', {'is-dragging': dragIndex === index}]"
        :style="getItemStyle(index)"
        @touchstart="handleTouchStart($event, index)"
        @touchmove="handleTouchMove"
        @touchend="handleTouchEnd"
      >
        <!-- 默认渲染方式 -->
        <view v-if="!$slots.default" class="default-item">
          <view class="item-left">
            <text class="item-index">{{ index + 1 }}</text>
          </view>
          <view class="item-body">
            <text class="item-title">{{ getItemTitle(item) }}</text>
            <text v-if="getItemDesc(item)" class="item-desc">{{ getItemDesc(item) }}</text>
          </view>
          <view class="item-right">
            <view class="drag-handle">
              <text class="handle-icon">≡</text>
            </view>
          </view>
        </view>
        
        <!-- 自定义渲染 -->
        <slot v-else :item="item" :index="index"></slot>
      </view>
    </view>
  </view>
</template>

<script setup>
import { ref, computed, watch } from 'vue';

// 定义组件属性
const props = defineProps({
  // 列表数据
  list: {
    type: Array,
    required: true,
    default: () => []
  },
  // 是否可拖拽
  draggable: {
    type: Boolean,
    default: true
  },
  // 列表项高度（单位px）
  itemHeight: {
    type: [Number, String],
    default: 80
  },
  // 标题字段名
  titleField: {
    type: String,
    default: 'title'
  },
  // 描述字段名
  descField: {
    type: String,
    default: 'desc'
  }
});

// 定义组件事件
const emit = defineEmits(['update:list', 'drag-start', 'drag-end', 'drag-change']);

// 内部数据
const displayList = ref([...props.list]);
const dragIndex = ref(-1); // 当前拖拽项索引
const targetIndex = ref(-1); // 目标位置索引
const startY = ref(0); // 拖拽开始位置
const startX = ref(0); // 拖拽开始位置
const offsetY = ref(0); // 拖拽偏移量
const isDragging = ref(false); // 是否正在拖拽

// 获取项目标题
const getItemTitle = (item) => {
  if (typeof item === 'string') return item;
  return item[props.titleField] || `项目 ${dragIndex.value + 1}`;
};

// 获取项目描述
const getItemDesc = (item) => {
  if (typeof item === 'string') return '';
  return item[props.descField] || '';
};

// 计算列表总高度
const listHeight = computed(() => {
  const height = typeof props.itemHeight === 'number' ? props.itemHeight : parseInt(props.itemHeight);
  return `${height * displayList.value.length}px`;
});

// 监听外部列表变化
watch(() => props.list, (newList) => {
  if (!isDragging.value) {
    displayList.value = [...newList];
  }
}, { deep: true });

// 获取列表项样式
const getItemStyle = (index) => {
  const height = typeof props.itemHeight === 'number' ? props.itemHeight : parseInt(props.itemHeight);
  
  // 计算每个项的位置
  if (isDragging.value && dragIndex.value === index) {
    return {
      transform: `translateY(${offsetY.value}px)`,
      zIndex: 10,
      transition: 'none'
    };
  }
  
  return {
    height: `${height}px`,
    transform: 'translateY(0)',
    transition: 'transform 0.3s'
  };
};

// 触摸开始
const handleTouchStart = (event, index) => {
  if (!props.draggable) return;
  
  dragIndex.value = index;
  startY.value = event.touches[0].clientY;
  startX.value = event.touches[0].clientX;
  isDragging.value = true;
  
  emit('drag-start', { 
    item: displayList.value[index],
    index
  });
  
  // 添加弹窗提示
  uni.showToast({
    title: `开始拖拽第${index + 1}项`,
    icon: 'none',
    duration: 800
  });
};

// 触摸移动
const handleTouchMove = (event) => {
  if (!isDragging.value || dragIndex.value < 0) return;
  
  const currentY = event.touches[0].clientY;
  offsetY.value = currentY - startY.value;
  
  // 计算当前拖拽项可能的目标位置
  const height = typeof props.itemHeight === 'number' ? props.itemHeight : parseInt(props.itemHeight);
  const dragDistance = Math.abs(offsetY.value);
  const direction = offsetY.value > 0 ? 1 : -1;
  
  // 计算移动的项数
  const moveCount = Math.floor(dragDistance / height);
  const newTargetIndex = Math.max(0, Math.min(displayList.value.length - 1, dragIndex.value + (moveCount * direction)));
  
  if (newTargetIndex !== targetIndex.value) {
    targetIndex.value = newTargetIndex;
  }
};

// 触摸结束
const handleTouchEnd = () => {
  if (!isDragging.value) return;
  
  // 如果拖拽到了新位置
  if (targetIndex.value >= 0 && targetIndex.value !== dragIndex.value) {
    // 更新列表顺序
    const newList = [...displayList.value];
    const [movedItem] = newList.splice(dragIndex.value, 1);
    newList.splice(targetIndex.value, 0, movedItem);
    
    displayList.value = newList;
    emit('update:list', newList);
    emit('drag-change', { 
      oldIndex: dragIndex.value,
      newIndex: targetIndex.value,
      item: movedItem,
      list: newList
    });
    
    // 添加弹窗提示
    uni.showToast({
      title: `项目已移动到第${targetIndex.value + 1}位`,
      icon: 'none',
      duration: 1500
    });
  }
  
  emit('drag-end', {
    item: displayList.value[targetIndex.value >= 0 ? targetIndex.value : dragIndex.value],
    index: targetIndex.value >= 0 ? targetIndex.value : dragIndex.value
  });
  
  // 重置状态
  dragIndex.value = -1;
  targetIndex.value = -1;
  offsetY.value = 0;
  isDragging.value = false;
};
</script>

<style lang="scss">
.xl-drag-list-container {
  width: 100%;
  position: relative;
  overflow: hidden;
  
  .drag-list {
    position: relative;
    width: 100%;
  }
  
  .drag-item {
    position: relative;
    width: 100%;
    touch-action: none;
    box-sizing: border-box;
    overflow: hidden;
    
    &.is-dragging {
      opacity: 0.8;
      box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
      z-index: 10;
    }
  }
  
  .default-item {
    padding: 8px 10px;
    background-color: #ffffff;
    border-bottom: 1px solid #f1f1f1;
    display: flex;
    align-items: center;
    
    .item-left {
      margin-right: 10px;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    
    .item-index {
      width: 26px;
      height: 26px;
      border-radius: 13px;
      background-color: #f2f2f2;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 14px;
      color: #666;
    }
    
    .item-body {
      flex: 1;
      overflow: hidden;
    }
    
    .item-title {
      font-size: 16px;
      color: #333;
      line-height: 1.5;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    
    .item-desc {
      font-size: 12px;
      color: #999;
      margin-top: 4px;
      line-height: 1.4;
    }
    
    .item-right {
      margin-left: 10px;
    }
    
    .drag-handle {
      width: 28px;
      height: 28px;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    
    .handle-icon {
      font-size: 20px;
      color: #ccc;
    }
  }
}
</style> 